/*
"JSFXGEN" - UIScrollBar.as
Modular Integrated Development Environment for JesuSonic
Project page: http://jsfxgen.googlecode.com

Copyright 2009 Lubomir I. Ivanov

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package neolit123.ui
{
  import flash.display.Sprite;
  import flash.display.Stage;
  import flash.display.MovieClip;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Rectangle;
  // =========================================================
  public class UIList extends Sprite
  {
    // =========================================================
    private var scroll_sp:Sprite;
    private var drag_mc:MovieClip;
    private var drag_sp:Sprite;
    private var drag:Box;
    private var smb:Box;
    private var track:Box;
    private var dmask:Box;
    private var stbkg:Box;
    private var stgt:Sprite;
    private var rect:Rectangle;
    private var range:Number;
    private var oldth:Number;
    private var oldh:Number;
    private var oldvs:Number;
    private var cheight:Number;
    private var smbmet:Number;
    private var total:int = 0;
    private var btnar:Array = [];
    public var btn:UIButton;
    public var selecteditem:Object = new Object();
    /*
    =========================================================
    parameters are:
    width, height, colordrag0, colordrag1, colortrack0, colortrack1, btnheight, colorbtn0, colorbtn1
    */
    public function UIList(...p:Array):void
    {
      // @ cacheAsBitmap = true;
      //cacheAsBitmap = true;
      // @ get properties
      if (p[0] == null || p[0] == undefined) p[0] = 200;
      if (p[1] == null || p[1] == undefined) p[1] = 200;
      if (p[2] == null || p[2] == undefined) p[2] = 0x0072ba;
      if (p[3] == null || p[3] == undefined) p[3] = 0x000000;
      if (p[4] == null || p[4] == undefined) p[4] = 0xeeeeee;
      if (p[5] == null || p[5] == undefined) p[5] = 0x000000;
      if (p[6] == null || p[6] == undefined) p[6] = 25;
      if (p[7] == null || p[7] == undefined) p[7] = 0x000000;
      if (p[8] == null || p[8] == undefined) p[8] = 0x000000;
      // @ create objects      
      drag = new Box(15,20,p[2],p[3],false);
      track = new Box(15,p[2],p[4],p[5],false);      
      dmask = new Box(p[0]-40,p[1]-40,0x00ff00,0x00ff00,false);
      // @ add item containter
      var stcont:Sprite = new Sprite;
      addChild(stcont);
      cheight = p[1];
      // @ add item containter bkg
      stbkg = new Box(p[0]-drag.width,p[1],0x999999,0x000000,false);
      // @ add small box on scroll
      smbmet = 15*0.5;
      smb = new Box(smbmet,smbmet,p[4],p[5],false);
      // @ add scroll target sprite 
      stgt = new Sprite();
      addChild(stgt);
      // @ arrange objects
      scroll_sp = new Sprite();
      drag_sp = new Sprite();
      drag_mc = new MovieClip();
      addChild(scroll_sp);
      scroll_sp.addChild(track);
      scroll_sp.addChild(drag_mc);
      drag_mc.addChild(drag_sp);
      drag_sp.addChild(drag);
      drag_sp.addChild(smb);
      // @ set small box to half size
      smb.x = (((15-smbmet)*0.5)>>0) + 1;
      // @ set drag
      drag_sp.buttonMode = true;
      drag_sp.mouseChildren = false;
      // @ add bkg
      stcont.addChild(stbkg);
      stcont.addChild(stgt);
      // @ add mask
      addChild(dmask);
      mask = dmask;
      // @ add drag listeners  
      drag_sp.addEventListener(MouseEvent.MOUSE_DOWN, startdrag);
      drag_sp.addEventListener(MouseEvent.MOUSE_OVER, rollover);
      drag_sp.addEventListener(MouseEvent.MOUSE_OUT, rollout);  
      // @ set track
      track.buttonMode = true;
      track.mouseChildren = false;
      track.addEventListener(MouseEvent.MOUSE_DOWN, clicktrack);
      // @ update scroller on text change
      stgt.addEventListener(Event.SCROLL, updatescroller);
      stgt.addEventListener(Event.CHANGE, updatescroller);
      // @ first update
      updatescroller(null);
      setsize(p[0],p[1]);
    }    
    // =========================================================
    // [ set drag dimentions
    // =========================================================
    private function setrect():void
    {
      range = cheight - drag_mc.height;
      rect = new Rectangle(0, 0, 0, range);
      updatescrollerposition(null);
    }
    // =========================================================
    // [ drag scroller
    // =========================================================
    private function startdrag(e:MouseEvent):void
    {
      drag.alpha = 0.8;
      drag_sp.removeEventListener(MouseEvent.MOUSE_OUT, rollout);
      drag_mc.stage.addEventListener(MouseEvent.MOUSE_UP, stopdrag);
      drag_mc.stage.addEventListener(Event.ENTER_FRAME, dragf);
      drag_mc.startDrag(false, rect);
      stgt.removeEventListener(Event.SCROLL, updatescroller);
    }
    // =========================================================
    // [ stop drag
    // =========================================================
    private function stopdrag(e:MouseEvent):void
    {
      drag.alpha = 1;
      drag_sp.addEventListener(MouseEvent.MOUSE_OUT, rollout);
      drag_mc.stage.removeEventListener(MouseEvent.MOUSE_UP, stopdrag);
      drag_mc.stage.removeEventListener(Event.ENTER_FRAME, dragf);
      drag_mc.stopDrag();
      stgt.addEventListener(Event.SCROLL, updatescroller);
    }
    // =========================================================
    // [ click on scroller track
    // =========================================================
    private function clicktrack(e:MouseEvent):void
    {
      drag_mc.y = e.localY*track.scaleY - drag_mc.height*0.5;
      startdrag(null);
    }
    // =========================================================
    // [ call scroll from drag
    // =========================================================
    private function dragf(e:Event):void
    {
      callscroll(drag_mc.y/range);
    }
    // =========================================================
    // [ call scroll
    // =========================================================
    private function callscroll(n:Number):void
    {
      stgt.y = -(stgt.height-cheight)*n;
    }
    // =========================================================
    // [ update scroll position
    // =========================================================
    private function updatescrollerposition(e:Event):void
    {      
      drag_mc.y = ((stgt.y-1)/(stgt.height-1))*range;
    }
    // =========================================================
    // [ update scroller from text height
    // =========================================================
    private function updatescroller(e:Event=null):void
    {
      var newth:Number = stgt.height;
      var vs:Number = stgt.y;
      // @ update metrics on (text)height change
      if (oldth != newth || oldh != cheight || oldvs != vs)
      {
        var esth:Number = cheight*cheight/newth;
        drag.alpha = 1;
        drag_sp.mouseEnabled = true;
        if (esth>cheight)
        {
          esth = cheight; drag.alpha = 0.3; drag_sp.mouseEnabled = false;
        } else if (esth < smbmet+5) esth = smbmet+5;
        drag.height = esth;
        smb.y = (esth - smbmet)*0.5;
        oldth = newth;
        oldh = cheight;
        oldvs = vs;
        setrect();
      }
    }
    // =========================================================
    // [ setsize (public)
    // =========================================================
    public function setsize(w:Number,h:Number):void
    {   
      var tmpw:Number = scroll_sp.x = stbkg.width = w-track.width;
      dmask.width = w+1;
      dmask.height = h+1;
      track.height = cheight = stbkg.height = h;
      // @ update btns
      var btnarlen:int = btnar.length;
      for (var i:int=0;i<btnarlen;i++)
      {
        btnar[i].setsize(tmpw,null);
      } 
      drag_mc.y=stgt.y=0;
      updatescroller(null);
    }    
    // =========================================================
    // [ additem (public)
    // =========================================================
    public function additem(l:String,d:*):void
    {   
      // @ add item
      btn = new UIButton(l, dmask.width-track.width, null, "left", true, null, null, null, false);
      btn.data = d;
      btn.label = l;
      btn.id = btnar.length;
      stgt.addChild(btn);
      btnar.push(btn);
      btn.y += 25*(btnar.length-1);
      // @ add single click mouse event
      btn.addEventListener(MouseEvent.CLICK, btnclick);
      function btnclick(e:MouseEvent):void
      {
        select(e.target.parent.id);
      }
      // @ update 
      drag_mc.y=stgt.y=0;
      updatescroller(null);
    }
    // =========================================================
    // [ select item
    // =========================================================
    public function select(id:int):void
    {
      // @ untogle all / toggle selected
      var btnarlen:int = btnar.length;
      for (var i:int=0;i<btnarlen;i++)
      {
        btnar[i].toggle(true);
      }
      btnar[id].toggle(false);
      // @ update selected item 
      selecteditem.id = id;
      selecteditem.label = btnar[id].label;
      selecteditem.data = btnar[id].data;
    }
    // =========================================================
    // [ rollover / rollout
    // =========================================================
    private function rollover(e:MouseEvent=null):void
    {
      drag.alpha = 0.8;
    }
    private function rollout(e:MouseEvent=null):void
    {
      drag.alpha = 1;
    }
  }
}